# -*- coding: utf-8 -*-

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache
from megafetch import Fetcher
from urllib import urlencode
import urllib

import nrk
import simplejson as json

cacheTimeoutStatic = 3600

def get_cached_item(key, updateFunc):
	val = memcache.get(key)
	if val is not None:
		return val
	else:
		val = updateFunc()
		if not memcache.add(key, val, cacheTimeoutStatic):
			pass
		return val

def get_cached_projects():
	return get_cached_item("projects", nrk.get_menu_projects)

def get_cached_theme_projects(themeId):
	return get_cached_item("projects_theme%s" % themeId, lambda:nrk.get_menu_theme_projects(themeId))

def get_cached_themes():
	return get_cached_item("themes", nrk.get_menu_themes)
	
def get_cached_podcasts(mediaType):
	return get_cached_item("podcasts_%s" % mediaType, lambda: get_podcasts(mediaType))


def get_podcasts(mediaType):
	pods = nrk.get_menu_podcasts()[mediaType]
	counter = len(pods)

	def updatePod(pod, response):
		raise Exception(response.content)
		rssDoc = nrk.parse_doc(response.content)
		pod["summary"] = unicode(rssDoc.find("itunes:summary").renderContents(), "utf-8")
		pod["description"] = unicode(rssDoc.find("itunes:description").renderContents(), "utf-8")
		pod["imageUrl"] = rssDoc.find("itunes:image")["href"]

	#fetcher = Fetcher()
	#for pod in pods:
	#	fetcher.start(pod["rssUrl"], lambda x: updatePod(pod, x))
	#fetcher.wait()

	return pods


def get_theme(themeId):
	themeId = int(themeId)
	theme = filter(lambda x: int(x["id"]) == themeId, get_cached_themes())[0]
	return theme


def get_project(projectId):
	projectId = int(projectId)
	project = filter(lambda x: int(x["id"]) == projectId, get_cached_projects())[0]


class BasicHandler(webapp.RequestHandler):
	def get(self, format, *args):
		data = self.get_data(*args)

		if format == "json":
			#self.response.headers['Content-Type'] = "application/json; charset=utf-8"
			self.response.headers['Content-Type'] = "text/plain; charset=utf-8"
			json.dump(data, self.response.out)

		elif format == "html":
			self.response.headers['Content-Type'] = "text/html; charset=utf-8"
			self.get_html(*(args + (data,)))

		elif format == "asx":
			#self.response.headers['Content-Type'] = "text/plain; charset=utf-8"
			self.response.headers['Content-Type'] = "video/x-ms-asx"
			self.get_asx(*(args + (data,)))

		elif format == "rss":
			self.response.headers["Content-Type"] = "application/xml; charset=utf-8"
			self.get_rss(*(args + (data,)))



class Podcasts(BasicHandler):
	"""
	Returns all Podcasts
	"""

	def get_data(self, mediaType):
		return get_cached_podcasts(mediaType)

	def get_html(self, mediaType, pods):
		def getLine(proj):
			return u"""
				<li>
					<h2>%(name)s</h2>
					<div>%(description)s</div>
					<div><a href="%(programUrl)s">Program Home Page</a></div>
					<div><a href="%(rssUrl)s" >rss url</a></div>
				</li>
			""" % proj
		lines = u"\n".join(map(getLine, pods))

		self.response.out.write(u"""
			<html>
			<head>
				<title>Podcasts (%s)</title>
			</head>
			<body>
				<h1>Podcasts (%s)</h1>
				<ul>%s</ul>
			</body>
			</title>
		""" % (mediaType, mediaType, lines,) )


	def get_rss(self, mediaType, pods):
		def get_item(pod):
			pod["rssUrl"] = pod["rssUrl"].replace("http://", "rss://")
			return u"""
			<item>
				<title>%(name)s</title>
				<description>%(description)s</description>
				<link>%(rssUrl)s</link>
				<boxee:image></boxee:image>
			</item>""" % pod

		items = "".join(map(get_item, pods))
		selfUrl = self.request.url
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>NRK Podcasts</title>
			<link>%(selfUrl)s</link>
			<description>NRK Video Podcasts</description>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="list"/>
					<boxee:view-option id="1" view-type="line"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>

			%(items)s

			</channel>
			</rss>
			""" % locals())



class Projects(BasicHandler):
	"""
	Returns all projects (program)
	"""

	def get_data(self, searchType, searchId):
		if searchType == "theme":
			themeId = int(searchId)
			projects = get_cached_theme_projects(themeId)
		elif searchType == "letter":
			letter = searchId[0].lower()
			projects = filter(lambda proj: proj["name"][0].lower() == letter, get_cached_projects())
		else:
			projects = get_cached_projects()
		return projects
		
	def get_html(self, searchType, searchId, projects):
		def getLine(proj):
			return """
				<li>
					<a href="/html/menu/project/%(id)s" >
						<img src="%(image)s" title="%(description)s"/> 
						%(name)s
					</a>
				</li>
			""" % proj
		lines = u"\n".join(map(getLine, projects))

		self.response.out.write(u"""
			<html>
			<head>
				<title>Programs</title>
			</head>
			<body>
				<h1>Programs</h1>
				<ul>%s</ul>
			</body>
			</title>
		""" % (lines,) )


	def get_rss(self, searchType, searchId, projects):
		if searchType == "theme":
			title = get_theme(searchId)["name"]
		elif searchId == "@" or searchType is None:
			title = "Alle Program"
		elif searchType == "letter":
			title = searchId
		else:
			raise Exception("Invalid search type %s" % searchType)

		def get_item(project):
			project["url"] = "rss://" + self.request.host + "/rss/menu/project/%i" % project["id"]
			return u"""
			<item>
				<title>%(name)s</title>
				<description>%(description)s</description>
				<link>%(url)s</link>
				<boxee:image>%(image)s</boxee:image>
			</item>""" % project

		items = "".join(map(get_item, projects))
		selfUrl = self.request.url
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>%(title)s</title>
			<link>%(selfUrl)s</link>
			<description>Program fra NRK Nett-TV</description>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="line"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>

			%(items)s

			</channel>
			</rss>
			""" % locals())




class Themes(BasicHandler):
	"""
	Returns all themes (temaer)
	"""
	def get_data(self):
		return get_cached_themes()

	def get_html(self, themes):
		def getLine(theme):	
			return u"""
				<li>
					<a href="/html/projects/theme/%(id)s">%(name)s</a>
				</li>
			""" % theme
		lines = u"\n".join(map(getLine, themes))

		self.response.out.write(u"""
			<html>
			<head>
				<title>Themes</title>
			</head>
			<body>
				<h1>Programs</h1>
				<ul>%s</ul>
			</body>
			</title>
		""" % (lines,) )


	def get_rss(self, themes):
		def get_item(theme):
			theme["url"] = "rss://" + self.request.host + "/rss/projects/theme/%i" % theme["id"]
			return u"""
			<item>
				<title>%(name)s</title>
				<link>%(url)s</link>
			</item>""" % theme

		items = "".join(map(get_item, themes))
		selfUrl = self.request.url
		podcastUrl ="rss://" + self.request.host + "/rss/podcasts" 
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>Temaer</title>
			<link>%(selfUrl)s</link>
			<description>Temaer fra NRK Nett-TV</description>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="list"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>
			<item>
				<title>Video Podcasts</title>
				<link>%(podcastUrl)s/video</link>
			</item>
			<item>
				<title>Audio Podcasts</title>
				<link>%(podcastUrl)s/audio</link>
			</item>
			%(items)s
			</channel>
			</rss>
			""" % locals())




class MenuHandler(BasicHandler):
	def get_data(self, itemId):
		itemId = int(itemId)
		return self.get_menu_items(itemId)
		
	def get_html(self, itemId, menuItems):
		itemId = int(itemId)
		def getLine(cat):
			cat["url"] = "../%s/%i" % (cat["type"], cat["id"],)
			line = u"%(name)s: " % cat
			if not cat["isLeaf"]:
				line += u"""<a href="%(url)s" title="%(description)s">sub items (%(type)s)</a> """ % cat
			if cat["mediaType"]:
				line += u"""<a href="/html/%(type)s/%(mediaType)s/%(id)i">%(mediaType)s</a>""" % cat
			
			return u"<li>%s</li>" % line
		lines = u"\n".join(map(getLine, menuItems))

		self.response.out.write(u"""
			<html>
			<head>
				<title>Menu Items for %i</title>
			</head>
			<body>
				<h1>Menu Items for %i</h1>
				<ul>%s</ul>
			</body>
			</title>
		""" % (itemId, itemId, lines,) )


class ProjectMenu(MenuHandler):
	def get_menu_items(self, projectId):
		projectId = int(projectId)
		return nrk.get_menu_categories(projectId)

	def get_rss(self, projectId, menuItems):
		title = get_project(projectId)

		def get_item(cat):
			if cat["mediaType"]:
				cat["url"] = u"rss://" + self.request.host + u"/rss/%(type)s/%(mediaType)s/%(id)i" % cat
			else:
				cat["url"] = u"rss://" + self.request.host + u"/rss/menu/%(type)s/%(id)i" % cat

			return u"""
				<item>
					<title>%(name)s</title>
					<link>%(url)s</link>
					<description>%(description)s</description>
				</item>""" % cat

		items = "".join(map(get_item, menuItems))
		selfUrl = self.request.url
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>%(title)s</title>
			<link>%(selfUrl)s</link>
			<description>Klipp fra %(title)s</description>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="list"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>
			%(items)s
			</channel>
			</rss>
			""" % locals())






class CategoryMenu(MenuHandler):
	def get_menu_items(self, categoryId):
		categoryId = int(categoryId)
		return nrk.get_menu_clips(categoryId)

	def get_rss(self, projectId, menuItems):
		title = "Category %s (fix title)" % projectId

		def get_item(cat):
			if cat["mediaType"]:
				cat["url"] = u"rss://" + self.request.host + u"/rss/%(type)s/%(mediaType)s/%(id)i" % cat
			else:
				cat["url"] = u"rss://" + self.request.host + u"/rss/menu/%(type)s/%(id)i" % cat

			return u"""
				<item>
					<title>%(name)s</title>
					<description>%(description)s</description>
					<link>%(url)s</link>
				</item>""" % cat

		items = "".join(map(get_item, menuItems))
		selfUrl = self.request.url
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>%(title)s</title>
			<link>%(selfUrl)s</link>
			<description>Klipp fra %(title)s</description>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="list"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>
			%(items)s
			</channel>
			</rss>
			""" % locals())





class ClipMenu(MenuHandler):
	def get_menu_items(self, clipId):
		clipId = int(clipId)
		return nrk.get_menu_clip_indices(clipId)


class Clip(BasicHandler):
	def get_data(self, clipType, mediaType, clipId):
		clipId = int(clipId)

		if clipType == "clip":
			asxUrl = nrk.get_asx_url_clip(clipId)
		elif clipType == "index":
			asxUrl = nrk.get_asx_url_clip_index(clipId)

		asx = nrk.get_asx(asxUrl)
		return {
			"url": "/asx/%s/%s/%i" % (clipType, mediaType, clipId),
			"origAsxUrl": asxUrl,
			"asx": asx,
			}

	def get_html(self, clipType, mediaType, clipId, clip):
		clipId = int(clipId)
		playerUrl = "/player/%i" % clipId
		self.response.out.write(u"""
			<html>
			<head>
				<title>Clip %i - %s</title>
			</head>
			<body>
				<h1>Media</h2>
				<ul>
					<li><a href="%s">mms</a></li>
					<li><a href="%s">asx</a></li>
					<li><a href="%s">player</a></li>
				</ul>
			</body>
			</title>
		""" % (clipId, clip["asx"]["name"], clip["asx"]["url"], clip["url"], playerUrl) )

	def get_rss(self, clipType, mediaType, clipId, clip):
		clipId = int(clipId)
		
		selfUrl = self.request.url
		title = clip["asx"]["name"]
		description = clip["asx"]["description"]

		mmsUrl = clip["asx"]["url"]
		asxUrl = clip["url"]
		
		playerUrl = urllib.quote("http://%s/player/%i" % (self.request.host, clipId))
		silverlightUrl = "flash://nrkbrowser.appspot.com/src=?%s&amp;bx-ourl=%s" % (playerUrl, playerUrl)
		
		self.response.out.write(u"""<?xml version="1.0" encoding="utf-8"?>
			<rss version="2.0" xmlns:boxee="http://boxee.tv/rss" xmlns:media="http://search.yahoo.com/mrss/">
			<channel>
			<title>%(title)s</title>
			<link>%(selfUrl)s</link>
			<language>no-nb</language>
			<boxee:display>
				<boxee:view default="1">
					<boxee:view-option id="1" view-type="list"/>
				</boxee:view>
				<boxee:sort default="1" folder-position="start">
					<boxee:sort-option id="1" sort-by="none" sort-type-name="default"/>
				</boxee:sort>
			</boxee:display>
			<item>
				<title>mms</title>
				<description>%(description)s</description>
				<link>%(mmsUrl)s</link>
				<media:content url="%(mmsUrl)s" type="video/x-ms-wmv" />
				<guid>%(mmsUrl)s</guid>
			</item>
			<item>
				<title>asx</title>
				<description>%(description)s</description>
				<link>%(asxUrl)s</link>
				<media:content url="%(asxUrl)s" type="video/x-ms-wmv" />
				<guid>%(asxUrl)s</guid>
			</item>
			<item>
				<title>player</title>
				<description>%(description)s</description>
				<link>%(silverlightUrl)s</link>
				<guid>%(silverlightUrl)s</guid>
			</item>
			</channel>
			</rss>""" % locals())

	def get_asx(self, clipType, mediaType, clipId, clip):
		self.response.headers["content-disposition"] = "inline; filename=%i.asx" % int(clipId)
		self.response.out.write((u"""
		<asx version="3.0">
			<param name="Encoding" value="utf-8" />
			<title>%(name)s</title>
			<abstract>%(description)s</abstract>
			<author>NRK - Norsk Rikskringkasting</author>
			<copyright>NRK - Norsk Rikskringkasting</copyright>
			<entry>
				<starttime value="%(starttime)s" />
				<duration value="%(duration)s" />
			 	<ref href="%(url)s" />
				<title>%(name)s</title>
				<author>NRK - Norsk Rikskringkasting</author>
				<abstract>%(description)s</abstract>
				<copyright>NRK - Norsk Rikskringkasting</copyright>
			</entry>
		</asx>
		""" % clip["asx"]).encode("utf-8"))
			

class Main(BasicHandler):
	def get(self, format):
		memcache.flush_all()
		self.response.headers['Content-Type'] = "text/html; charset=utf-8"
		letters = range(0,10) + [chr(i) for i in range(ord("a"), ord("z")+1)] + [u"æ", u"ø", u"å"]
		letterHtml = " ".join(["<a href=""/html/projects/letter/%s"">%s</a>" % (l, l) for l in letters])
		self.response.out.write(u"""
			<html>
			<head>
				<title>NRK Browser</title>
			</head>
			<body>
				<h1>NRK Browser</h1>
				<div>All pages are available in html and json format, decided by the path prefix in the url.</div>
				<ul>
					<li>Projects starting with %s</li>
					<li><a href="/html/projects">All Projects"</a></li>
					<li><a href="/html/themes">All Themes</a></li>
					<li><a href="/html/podcasts/video">Video Podcasts</a></li>
					<li><a href="/html/podcasts/audio">Audio Podcasts</a></li>
				</ul>
			</body>
			</title>
		""" % (letterHtml,) )


class SilverlightMediaXml(BasicHandler):
	def get(self, clipId):
		clipId = int(clipId)
		url = nrk.get_url_mediaxml(clipId)
		doc = nrk.get_raw_doc(url)

		self.response.headers["Content-Type"] = "text/xml; charset=utf-8"
		self.response.out.write(doc)

class SilverlightPlayer(BasicHandler):
	def get(self, clipId):
		clipId = int(clipId)
	
		mediaXmlUrl = "/mediaxml/%i" % clipId
	
		self.response.out.write(u"""
			<html>
			<head>
				<script type="text/javascript" src="/static/startplayer_16.9_internal.js"></script>
				<script type="text/javascript" src="/static/nrkplayer3.js"></script>
				<script type="text/javascript" src="/static/Silverlight.js"></script>
			</head>
			<body>
				<div id="ctl00_ucPlayer_ObjectWrapper" class="objectWrapper"></div>
				<script type="text/javascript">
					player = new NRKPlayer('ctl00_ucPlayer_ObjectWrapper',"%(mediaXmlUrl)s", 0.5, true, false, true)
				</script>
			</body>
		""" % locals())

class Flush(webapp.RequestHandler):
	def get(self):
		memcache.flush_all()
		self.response.out.write(memcache.get_stats())



application = webapp.WSGIApplication(
	[
		("/(json|html|rss)/podcasts/(video|audio)", Podcasts), 
		("/(json|html|rss)/projects/?(theme|letter)?/?(.*)", Projects), 
		("/(json|html|rss)/themes", Themes),
		("/(json|html|rss)/menu/project/([0-9]*)", ProjectMenu), 
		("/(json|html|rss)/menu/category/([0-9]*)", CategoryMenu), 
		("/(json|html|rss)/menu/clip/([0-9]*)", ClipMenu),
		("/(json|html|rss|asx)/(clip|index)/(audio|video)/([0-9]*)", Clip),
		("/mediaxml/([0-9]*)", SilverlightMediaXml),
		("/player/([0-9]*)", SilverlightPlayer),
		("/(rss)?", Main),
		("/flushcache", Flush),
	],
	debug=True,
	)

if __name__ == "__main__":
	run_wsgi_app(application)
